home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / cmdity / realdrag.lha / RealDrag.c < prev    next >
C/C++ Source or Header  |  1996-04-26  |  10KB  |  421 lines

  1. /*    $VER: RealDrag.c 1.0 (23.4.96)
  2.     RealDrag by Stuart Monteith
  3.  
  4.     Allows windows to be dragged, while their contents are still shown.
  5.  
  6.     Note: This source is Public Domain. Hell, this program should have been
  7.         written years ago.
  8. */
  9.  
  10. #include    <dos/dos.h>
  11. #include    <devices/inputevent.h>
  12. #include    <exec/types.h>
  13. #include    <exec/libraries.h>
  14. #include    <intuition/intuitionbase.h>
  15. #include    <libraries/commodities.h>
  16. #include     <workbench/startup.h>
  17. #include     <workbench/workbench.h>
  18.  
  19. #include    <clib/exec_protos.h>
  20. #include    <clib/commodities_protos.h>
  21. #include    <clib/icon_protos.h>
  22.  
  23. struct NewBroker newBroker=    {
  24.     NB_VERSION,
  25.     "RealDrag",
  26.     "RealDrag 1.0 Apr-96 Stuart Monteith",
  27.     "Alternative filled window dragging",
  28.     NBU_NOTIFY | NBU_UNIQUE,    /* Tell me when another me is started */
  29.     0,            /* No flags. ie. no Show & Hide */
  30.     4,            /* Priority. To be set */
  31.     NULL,        /* Message port. To Be Set */
  32.     0            /* Unused */
  33. };
  34.  
  35. void Cleanup(char *errStr,ULONG errNum);    /* Call to exit */
  36. void RealMain(void);
  37.  
  38. /* This is a custom CxObject, to be executed on input.device's task.
  39.  * __geta4 as we are compiled as a small-code model.                 */
  40. __geta4 void CxStripQualifier(CxMsg *cxm,CxObj *co);
  41.  
  42. struct IntuitionBase *IntuitionBase=NULL;
  43. struct Library *CxBase=NULL,*IconBase=NULL;
  44. extern struct Library *DOSBase;
  45.  
  46.  
  47. struct MsgPort    *msgPort=NULL;
  48.  
  49. CxObj    *broker=NULL,*filter=NULL,*sender=NULL,*stripqual=NULL;
  50.  
  51. #define    CXID_SENDER1    0xCED1
  52.  
  53. /* Used by filter to direct mouse movements to us */
  54. IX    ix = {
  55.     IX_VERSION,            /* IXVersion */
  56.     IECLASS_RAWMOUSE,    /* Class */
  57.     0,        /* Code  */
  58.     0,        /* CodeMask*/
  59.     0,    /* Qualifier */
  60.     0,    /* Qualifier mask */
  61.     0};
  62.  
  63. char *vers="$VER: RealDrag.c 1.0 (23.4.96)";
  64.  
  65. /*     ReadArgs */
  66. #define NUM_ARGS    12    /* # of args */
  67.  
  68. /* The ReadArgs array indices */
  69. #define ARG_CX_PRIORITY    0
  70. #define ARG_TASKPRI    1
  71. #define ARG_CTRL    2
  72. #define ARG_LSHIFT    3
  73. #define ARG_RSHIFT    4
  74. #define ARG_LALT     5
  75. #define ARG_RALT    6
  76. #define ARG_LAMIGA    7
  77. #define ARG_RAMIGA    8
  78. #define ARG_LBUTTON    9
  79. #define    ARG_RBUTTON 10
  80. #define ARG_MBUTTON 11
  81.  
  82. /* The ReadArgs template */
  83. char *template="CX_PRIORITY/N/K,TASKPRI/N/K,CTRL/S"
  84.     ",LSHIFT/S,RSHIFT/S,LALT/S,RALT/S,LAMIGA/S,RAMIGA/S,"
  85.     "LBUTTON/S,RBUTTON/S,MBUTTON/S";
  86. LONG    Args[NUM_ARGS];
  87. struct RDArgs    *rdArgs = NULL;
  88.  
  89. BOOL FromWB;    /* True if launched from WB, false if from DOS */
  90.  
  91. /* An EasyRequester displaying an error from WB */
  92. struct EasyStruct    ez ={
  93.     sizeof(struct EasyStruct),    /* Struct Size */
  94.     0,    /* Flags */
  95.     "RealDrag",    /* Title */
  96.     "Error:\n%s",        /* Text Format */
  97.     "Understood"        /* Gadget Format */
  98. };
  99.  
  100.  
  101. /* Workbench startup stuff */
  102. int wbmain(struct WBStartup *ws)
  103. {
  104.     struct WBArg     *wbArg;
  105.     struct DiskObject    *icon;
  106.     BPTR    oldlock;
  107.     char *tt;    /* ToolType */
  108.  
  109.     FromWB=TRUE;
  110.  
  111.     if(!(IconBase = OpenLibrary("icon.library",36)))
  112.         Cleanup("Unable to open icon.library V36",
  113.                     ERROR_INVALID_RESIDENT_LIBRARY);
  114.  
  115.     /* If just Tool icon, use that, else use first project icon */
  116.     if(ws->sm_NumArgs == 1)
  117.         wbArg = &(ws->sm_ArgList[0]);
  118.     else
  119.         wbArg = &(ws->sm_ArgList[1]);
  120.  
  121.     oldlock = CurrentDir(wbArg->wa_Lock);
  122.  
  123.     if(!(icon = (struct DiskObject *) GetDiskObject(wbArg->wa_Name)))
  124.     {
  125.         CurrentDir(oldlock);    /* Important!*/
  126.         Cleanup("Unable to get icon",IoErr());
  127.     }
  128.     CurrentDir(oldlock);
  129.  
  130.     if(tt = FindToolType(icon->do_ToolTypes,"CX_PRIORITY"))
  131.         newBroker.nb_Pri = (BYTE) atoi(tt);
  132.  
  133.     /* All of these args may follow `QUALIFIER=', separated by | */
  134.     if(tt = FindToolType(icon->do_ToolTypes,"QUALIFIER"))
  135.     {
  136.         if(MatchToolValue(tt,"CTRL"))
  137.             ix.ix_Qualifier |= IEQUALIFIER_CONTROL;
  138.  
  139.         if(MatchToolValue(tt,"LSHIFT"))
  140.             ix.ix_Qualifier |= IEQUALIFIER_LSHIFT;
  141.  
  142.         if(MatchToolValue(tt,"RSHIFT"))
  143.             ix.ix_Qualifier |= IEQUALIFIER_RSHIFT;
  144.  
  145.         if(MatchToolValue(tt,"LALT"))
  146.             ix.ix_Qualifier |= IEQUALIFIER_LALT;
  147.  
  148.         if(MatchToolValue(tt,"RALT"))
  149.             ix.ix_Qualifier |= IEQUALIFIER_RALT;
  150.  
  151.         if(MatchToolValue(tt,"LAMIGA"))
  152.             ix.ix_Qualifier |= IEQUALIFIER_LCOMMAND;
  153.  
  154.         if(MatchToolValue(tt,"RAMIGA"))
  155.             ix.ix_Qualifier |= IEQUALIFIER_RCOMMAND;
  156.  
  157.         if(MatchToolValue(tt,"LBUTTON"))
  158.             ix.ix_Qualifier |= IEQUALIFIER_LEFTBUTTON;
  159.  
  160.         if(MatchToolValue(tt,"RBUTTON"))
  161.             ix.ix_Qualifier |= IEQUALIFIER_RBUTTON;
  162.  
  163.         if(MatchToolValue(tt,"MBUTTON"))
  164.             ix.ix_Qualifier |= IEQUALIFIER_MIDBUTTON;
  165.     }
  166.  
  167.     FreeDiskObject(icon);
  168.  
  169.     RealMain();
  170. }
  171.  
  172. int main(int argc,char *argv[])
  173. {
  174.     int cnt;
  175.  
  176.     FromWB = FALSE;
  177.  
  178.     if(DOSBase->lib_Version <36)
  179.     {
  180.         printf("RealDrag: Wrong DOS version - upgrade to 2.0 or above!\n");
  181.         exit(ERROR_INVALID_RESIDENT_LIBRARY);
  182.     }
  183.  
  184.     /* NULL all args */
  185.     for(cnt=0;cnt < NUM_ARGS;cnt++) Args[cnt] = 0l;
  186.     
  187.     if(!(rdArgs = (struct RDArgs *) ReadArgs(template,Args,NULL)))
  188.     {
  189.         PrintFault(ERROR_REQUIRED_ARG_MISSING,"RealDrag: ");
  190.         exit(ERROR_REQUIRED_ARG_MISSING);
  191.     }
  192.  
  193.     if(Args[ARG_CX_PRIORITY])
  194.         newBroker.nb_Pri = (BYTE) *((LONG *) Args[ARG_CX_PRIORITY]);
  195.  
  196.     if(Args[ARG_TASKPRI])
  197.         SetTaskPri(FindTask(NULL),*((LONG *) Args[ARG_TASKPRI]));
  198.  
  199.     if(Args[ARG_CTRL])
  200.         ix.ix_Qualifier |= IEQUALIFIER_CONTROL;
  201.  
  202.     if(Args[ARG_LSHIFT])
  203.         ix.ix_Qualifier |= IEQUALIFIER_LSHIFT;
  204.  
  205.     if(Args[ARG_RSHIFT])
  206.         ix.ix_Qualifier |= IEQUALIFIER_RSHIFT;
  207.  
  208.     if(Args[ARG_LALT])
  209.         ix.ix_Qualifier |= IEQUALIFIER_LALT;
  210.  
  211.     if(Args[ARG_RALT])
  212.         ix.ix_Qualifier |= IEQUALIFIER_RALT;
  213.  
  214.     if(Args[ARG_LAMIGA])
  215.         ix.ix_Qualifier |= IEQUALIFIER_LCOMMAND;
  216.  
  217.     if(Args[ARG_RAMIGA])
  218.         ix.ix_Qualifier |= IEQUALIFIER_RCOMMAND;
  219.  
  220.     if(Args[ARG_LBUTTON])
  221.         ix.ix_Qualifier |= IEQUALIFIER_LEFTBUTTON;
  222.  
  223.     if(Args[ARG_RBUTTON])
  224.         ix.ix_Qualifier |= IEQUALIFIER_RBUTTON;
  225.  
  226.     if(Args[ARG_MBUTTON])
  227.         ix.ix_Qualifier |= IEQUALIFIER_MIDBUTTON;
  228.  
  229.     RealMain();
  230. }
  231.  
  232. void    RealMain(void)
  233. {
  234.     LONG brokerErr;
  235.  
  236.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",36L)))
  237.         Cleanup("Unable to open intuition.library",36);
  238.  
  239.     if(!(CxBase = OpenLibrary("commodities.library",36)))
  240.         Cleanup("Unable to open commodities.library",
  241.                 ERROR_INVALID_RESIDENT_LIBRARY);
  242.  
  243.     if(!(msgPort = CreateMsgPort()))
  244.         Cleanup("Unable to create msgport",
  245.                 RETURN_FAIL);
  246.  
  247.     /* We care about our qualifiers */
  248.     ix.ix_QualMask = ix.ix_Qualifier;
  249.  
  250.     newBroker.nb_Port = msgPort;
  251.  
  252.     if(!(broker = CxBroker(&newBroker,&brokerErr)))
  253.     {
  254.         switch(brokerErr)
  255.         {
  256.             case CBERR_SYSERR:
  257.                 Cleanup("Can't create broker - syserr",RETURN_FAIL);
  258.             case CBERR_DUP:
  259.                 Cleanup(NULL,0);
  260.             case CBERR_VERSION:
  261.                 Cleanup("Wrong NewBroker struct version.",RETURN_FAIL);
  262.             default:
  263.                 Cleanup("Can't create broker - don't know why",RETURN_FAIL);
  264.         }
  265.     }
  266.  
  267.     /* Checks for qualifier AFTER trying to create broker. This allows realdrag
  268.      *    to kill itself without any arguments being present. */
  269.     if(! ix.ix_Qualifier)
  270.         Cleanup("You MUST choose a qualifier!",ERROR_REQUIRED_ARG_MISSING);
  271.  
  272.     if(!(filter = CxFilter("rawmouse ctrl leftbutton lmouse")))
  273.         Cleanup("Unable to create filter",RETURN_FAIL);
  274.  
  275.     SetFilterIX(filter,&ix);
  276.  
  277.     if(!(sender = CxSender(msgPort,CXID_SENDER1)))
  278.         Cleanup("Unable to create sender",RETURN_FAIL);
  279.  
  280.     if(!(stripqual = CxCustom(CxStripQualifier,0)))
  281.         Cleanup("Unable to create custom `CxStripQualifier'",RETURN_FAIL);
  282.  
  283.     AttachCxObj(broker,filter);
  284.     AttachCxObj(filter,sender);
  285.     AttachCxObj(filter,stripqual);
  286.  
  287.     {    WORD quit=0;
  288.         CxMsg *msg;
  289.         WORD cx=0,cy=0,lx,ly,nx,ny;
  290.         ULONG signal,msgid,msgtype,msgmask,brkmask,waitmask;
  291.         struct InputEvent ie;
  292.         struct Window *aw,*lw;
  293.  
  294.         msgmask = 1 << msgPort->mp_SigBit;
  295.         brkmask = SIGBREAKF_CTRL_C;
  296.         waitmask = msgmask | brkmask;
  297.  
  298.         ActivateCxObj(broker,1);
  299.  
  300.         while(!quit)
  301.         {
  302.             signal = Wait(waitmask);
  303.  
  304.             if(signal & msgmask){
  305.             while(msg = (CxMsg *) GetMsg(msgPort))
  306.             { 
  307.                 msgid = CxMsgID(msg);
  308.                 msgtype = CxMsgType(msg);
  309.                 if(msgtype == CXM_IEVENT)
  310.                     ie = *((struct InputEvent *) CxMsgData(msg));
  311.  
  312.                 ReplyMsg((struct Message *) msg);
  313.  
  314.                 switch(msgtype)
  315.                 {
  316.                     case CXM_IEVENT:
  317.                         if(msgid == CXID_SENDER1)
  318.                         {
  319.                             if(!(ie.ie_Qualifier & 
  320.                                 (~(ix.ix_Qualifier | 0x8c00))))
  321.                             {    aw = IntuitionBase->ActiveWindow;
  322.                                  /* only drag dragable windows! */
  323.                                   if(aw->Flags & WFLG_DRAGBAR)
  324.                                 {
  325.                                     nx = aw->WScreen->MouseX - (aw->Width>>1);
  326.                                     ny = aw->WScreen->MouseY - (aw->Height>>1);
  327.                                     /* Move window only if to new pos. */
  328.                                     if(!((aw == lw) &&
  329.                                          (nx == lx) && (ny == ly)))
  330.                                     { 
  331.                                         MoveWindow(aw,
  332.                                         nx - aw->LeftEdge,ny-aw->TopEdge);
  333.                                     }
  334.                                      lx = nx; ly = ny; lw = aw;
  335.                                 }
  336.                             }
  337.                         }
  338.                     break;
  339.  
  340.                     case CXM_COMMAND:
  341.                         switch(msgid)
  342.                         {
  343.                             case CXCMD_DISABLE:
  344.                                 ActivateCxObj(broker,0);
  345.                                 break;
  346.                             case CXCMD_ENABLE:
  347.                                 ActivateCxObj(broker,1);
  348.                                 break;
  349.                             /* If run twice or CX said so, die */
  350.                             case CXCMD_UNIQUE:
  351.                             case CXCMD_KILL:
  352.                                 quit = 1;
  353.                                 break;
  354.                         }
  355.                         break;
  356.                 }
  357.             }}
  358.             else if(signal & brkmask)
  359.                 quit = 1;
  360.         }
  361.     }
  362.  
  363.     Cleanup(NULL,0);
  364. }
  365.  
  366. /* This my Custom CX object. As a CxTranslate(NULL) couldn't be used (it
  367. stripped off the mouse movements), I need this to simply strip off the
  368. qualifiers & codes allowing intuition to move the pointer.   */
  369. __geta4 void CxStripQualifier(CxMsg *cxm,CxObj *co)
  370. {
  371.     struct InputEvent *ie;
  372.  
  373.     ie = (struct InputEvent *) CxMsgData(cxm);
  374.  
  375.     /* Only remove when I am dragging - using same critera. */
  376.     if(!(ie->ie_Qualifier & ~(ix.ix_Qualifier | 0x8c00)))
  377.     {    ie->ie_Qualifier = 0;
  378.         ie->ie_Code = 0;
  379.     }
  380. }
  381.  
  382. /* Cleans up, no matter what */
  383. void Cleanup(char *errStr,ULONG errNum)
  384. {
  385.     if(stripqual)
  386.         DeleteCxObj(stripqual);
  387.     if(sender)
  388.         DeleteCxObj(sender);
  389.     if(filter)
  390.         DeleteCxObj(filter);
  391.     if(broker)
  392.         DeleteCxObj(broker);
  393.     if(msgPort)
  394.         DeletePort(msgPort);
  395.     if(CxBase)
  396.         CloseLibrary(CxBase);
  397.     if(rdArgs)
  398.         FreeArgs(rdArgs);
  399.     if(IconBase)
  400.         CloseLibrary(IconBase);
  401.  
  402.     if(errStr)
  403.     {
  404.         if(FromWB)
  405.         {
  406.             if(!IntuitionBase)
  407.                 IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",36l);
  408.  
  409.             if(IntuitionBase)
  410.                 EasyRequest(NULL,&ez,NULL,errStr);    
  411.         }
  412.         else
  413.             printf("RealDrag: %s\n",errStr);
  414.     }
  415.  
  416.     if(IntuitionBase)
  417.         CloseLibrary((struct Library *)IntuitionBase);
  418.  
  419.     exit(errNum);
  420. }
  421.